package com.carol.lmsbe.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.carol.lmsbe.dto.*;
import com.carol.lmsbe.entity.Equipment;
import com.carol.lmsbe.entity.EquipmentBorrow;
import com.carol.lmsbe.entity.User;
import com.carol.lmsbe.mapper.EquipmentBorrowMapper;
import com.carol.lmsbe.mapper.EquipmentMapper;
import com.carol.lmsbe.mapper.UserMapper;
import com.carol.lmsbe.service.EquipmentBorrowService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.time.LocalDateTime;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 设备借用服务实现
 */
@Service
@RequiredArgsConstructor
@Slf4j
public class EquipmentBorrowServiceImpl implements EquipmentBorrowService {

    private final EquipmentBorrowMapper equipmentBorrowMapper;
    private final EquipmentMapper equipmentMapper;
    private final UserMapper userMapper;

    @Override
    public Page<EquipmentBorrowDTO> listBorrowRecords(EquipmentBorrowQueryRequest request) {
        Page<EquipmentBorrow> page = new Page<>(request.getPageNum(), request.getPageSize());
        
        LambdaQueryWrapper<EquipmentBorrow> queryWrapper = new LambdaQueryWrapper<>();
        
        if (request.getEquipmentId() != null) {
            queryWrapper.eq(EquipmentBorrow::getEquipmentId, request.getEquipmentId());
        }
        if (request.getBorrowerId() != null) {
            queryWrapper.eq(EquipmentBorrow::getBorrowerId, request.getBorrowerId());
        }
        if (StringUtils.hasText(request.getStatus())) {
            queryWrapper.eq(EquipmentBorrow::getStatus, request.getStatus());
        }
        if (request.getBorrowDateStart() != null) {
            queryWrapper.ge(EquipmentBorrow::getBorrowDate, request.getBorrowDateStart());
        }
        if (request.getBorrowDateEnd() != null) {
            queryWrapper.le(EquipmentBorrow::getBorrowDate, request.getBorrowDateEnd());
        }
        if (request.getReturnDateStart() != null) {
            queryWrapper.ge(EquipmentBorrow::getActualReturnDate, request.getReturnDateStart());
        }
        if (request.getReturnDateEnd() != null) {
            queryWrapper.le(EquipmentBorrow::getActualReturnDate, request.getReturnDateEnd());
        }
        
        queryWrapper.orderByDesc(EquipmentBorrow::getCreateTime);
        
        Page<EquipmentBorrow> borrowPage = equipmentBorrowMapper.selectPage(page, queryWrapper);
        
        // 转换为DTO
        Page<EquipmentBorrowDTO> result = new Page<>();
        BeanUtils.copyProperties(borrowPage, result, "records");
        
        List<EquipmentBorrowDTO> records = borrowPage.getRecords().stream().map(borrow -> {
            EquipmentBorrowDTO dto = new EquipmentBorrowDTO();
            BeanUtils.copyProperties(borrow, dto);
            
            // 手动映射字段名不匹配的属性
            dto.setBorrowTime(borrow.getBorrowDate());
            dto.setExpectedReturnTime(borrow.getExpectedReturnDate());
            dto.setActualReturnTime(borrow.getActualReturnDate());
            dto.setBorrowPurpose(borrow.getPurpose());
            
            // 设置设备名称和编号
            if (borrow.getEquipmentId() != null) {
                Equipment equipment = equipmentMapper.selectById(borrow.getEquipmentId());
                if (equipment != null) {
                    dto.setEquipmentName(equipment.getName());
                    dto.setEquipmentCode(equipment.getCode());
                }
            }
            
            // 设置借用人信息
            if (borrow.getBorrowerId() != null) {
                User borrowerUser = userMapper.selectById(borrow.getBorrowerId());
                if (borrowerUser != null) {
                    dto.setBorrowerName(borrowerUser.getRealName());
                    dto.setBorrowerPhone(borrowerUser.getPhone());
                    dto.setBorrowerDepartment(borrowerUser.getLaboratoryId() != null ? 
                        "实验室" + borrowerUser.getLaboratoryId() : null);
                }
            }
            
            return dto;
        }).collect(Collectors.toList());
        
        result.setRecords(records);
        return result;
    }

    @Override
    public EquipmentBorrowDTO getBorrowRecordById(Long id) {
        EquipmentBorrow borrow = equipmentBorrowMapper.selectById(id);
        if (borrow == null) {
            throw new RuntimeException("借用记录不存在");
        }
        
        EquipmentBorrowDTO dto = new EquipmentBorrowDTO();
        BeanUtils.copyProperties(borrow, dto);
        
        // 手动映射字段名不匹配的属性
        dto.setBorrowTime(borrow.getBorrowDate());
        dto.setExpectedReturnTime(borrow.getExpectedReturnDate());
        dto.setActualReturnTime(borrow.getActualReturnDate());
        dto.setBorrowPurpose(borrow.getPurpose());
        
        // 设置设备名称和编号
        if (borrow.getEquipmentId() != null) {
            Equipment equipment = equipmentMapper.selectById(borrow.getEquipmentId());
            if (equipment != null) {
                dto.setEquipmentName(equipment.getName());
                dto.setEquipmentCode(equipment.getCode());
            }
        }
        
        // 设置借用人信息
        if (borrow.getBorrowerId() != null) {
            User borrowerUser = userMapper.selectById(borrow.getBorrowerId());
            if (borrowerUser != null) {
                dto.setBorrowerName(borrowerUser.getRealName());
                dto.setBorrowerPhone(borrowerUser.getPhone());
                dto.setBorrowerDepartment(borrowerUser.getLaboratoryId() != null ? 
                    "实验室" + borrowerUser.getLaboratoryId() : null);
            }
        }
        
        return dto;
    }

    @Override
    @Transactional
    public EquipmentBorrowDTO borrowEquipment(EquipmentBorrowRequest request) {
        // 检查设备是否存在且可用
        Equipment equipment = equipmentMapper.selectById(request.getEquipmentId());
        if (equipment == null) {
            throw new RuntimeException("设备不存在");
        }
        if (!"NORMAL".equals(equipment.getStatus())) {
            throw new RuntimeException("设备不可用");
        }
        
        // 获取当前用户ID
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        Long currentUserId = getCurrentUserId(authentication);
        
        EquipmentBorrow borrow = new EquipmentBorrow();
        borrow.setEquipmentId(request.getEquipmentId());
        borrow.setBorrowerId(currentUserId);
        borrow.setLaboratoryId(equipment.getLaboratoryId());
        borrow.setBorrowDate(request.getBorrowDate());
        borrow.setExpectedReturnDate(request.getExpectedReturnDate());
        borrow.setPurpose(request.getBorrowPurpose());
        borrow.setStatus("BORROWED"); // 默认状态为已借用
        borrow.setRemark(request.getNote());
        
        equipmentBorrowMapper.insert(borrow);
        
        // 更新设备状态为已借用
        equipment.setStatus("BORROWED");
        equipmentMapper.updateById(equipment);
        
        return getBorrowRecordById(borrow.getId());
    }

    @Override
    @Transactional
    public EquipmentBorrowDTO returnEquipment(EquipmentBorrowReturnRequest request) {
        EquipmentBorrow borrow = equipmentBorrowMapper.selectById(request.getBorrowId());
        if (borrow == null) {
            throw new RuntimeException("借用记录不存在");
        }
        
        // 只有已借用状态的记录才能归还
        if (!"BORROWED".equals(borrow.getStatus())) {
            throw new RuntimeException("只有已借用状态的记录才能归还");
        }
        
        borrow.setActualReturnDate(request.getReturnDate());
        borrow.setStatus("RETURNED");
        if (StringUtils.hasText(request.getRemark())) {
            borrow.setRemark(request.getRemark());
        }
        
        equipmentBorrowMapper.updateById(borrow);
        
        // 更新设备状态为可用
        Equipment equipment = equipmentMapper.selectById(borrow.getEquipmentId());
        if (equipment != null) {
            equipment.setStatus("NORMAL");
            equipmentMapper.updateById(equipment);
        }
        
        return getBorrowRecordById(borrow.getId());
    }

    @Override
    @Transactional
    public EquipmentBorrowDTO updateBorrowRecord(EquipmentBorrowUpdateRequest request) {
        EquipmentBorrow borrow = equipmentBorrowMapper.selectById(request.getId());
        if (borrow == null) {
            throw new RuntimeException("借用记录不存在");
        }
        
        BeanUtils.copyProperties(request, borrow);
        equipmentBorrowMapper.updateById(borrow);
        
        return getBorrowRecordById(borrow.getId());
    }

    @Override
    @Transactional
    public void deleteBorrowRecord(Long id) {
        EquipmentBorrow borrow = equipmentBorrowMapper.selectById(id);
        if (borrow == null) {
            throw new RuntimeException("借用记录不存在");
        }
        
        equipmentBorrowMapper.deleteById(id);
    }

    @Override
    @Transactional
    public EquipmentBorrowDTO approveBorrowApplication(EquipmentBorrowApprovalRequest request) {
        EquipmentBorrow borrow = equipmentBorrowMapper.selectById(request.getBorrowId());
        if (borrow == null) {
            throw new RuntimeException("借用记录不存在");
        }
        
        // 只有待审批状态的记录才能审批
        if (!"PENDING".equals(borrow.getStatus())) {
            throw new RuntimeException("只有待审批状态的记录才能审批");
        }
        
        borrow.setStatus(request.getStatus());
        if (StringUtils.hasText(request.getApprovalComment())) {
            borrow.setRemark(request.getApprovalComment());
        }
        
        equipmentBorrowMapper.updateById(borrow);
        
        // 如果审批通过，更新设备状态
        if ("APPROVED".equals(request.getStatus())) {
            Equipment equipment = equipmentMapper.selectById(borrow.getEquipmentId());
            if (equipment != null) {
                equipment.setStatus("BORROWED");
                equipmentMapper.updateById(equipment);
            }
        }
        
        return getBorrowRecordById(borrow.getId());
    }

    @Override
    @Transactional
    public EquipmentBorrowDTO approveReturnApplication(EquipmentBorrowReturnApprovalRequest request) {
        EquipmentBorrow borrow = equipmentBorrowMapper.selectById(request.getBorrowId());
        if (borrow == null) {
            throw new RuntimeException("借用记录不存在");
        }
        
        // 只有已借用状态的记录才能审批归还
        if (!"BORROWED".equals(borrow.getStatus())) {
            throw new RuntimeException("只有已借用状态的记录才能审批归还");
        }
        
        borrow.setStatus(request.getStatus());
        if (StringUtils.hasText(request.getApprovalComment())) {
            borrow.setRemark(request.getApprovalComment());
        }
        
        equipmentBorrowMapper.updateById(borrow);
        
        // 如果审批通过，更新设备状态
        if ("RETURNED".equals(request.getStatus())) {
            Equipment equipment = equipmentMapper.selectById(borrow.getEquipmentId());
            if (equipment != null) {
                equipment.setStatus("NORMAL");
                equipmentMapper.updateById(equipment);
            }
        }
        
        return getBorrowRecordById(borrow.getId());
    }

    @Override
    public Page<EquipmentBorrowDTO> getMyBorrowRecords(EquipmentBorrowQueryRequest request) {
        // 获取当前用户ID
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        Long currentUserId = getCurrentUserId(authentication);
        
        request.setBorrowerId(currentUserId);
        return listBorrowRecords(request);
    }

    @Override
    public Page<EquipmentBorrowDTO> getPendingBorrowApplications(EquipmentBorrowQueryRequest request) {
        request.setStatus("PENDING");
        return listBorrowRecords(request);
    }

    @Override
    public Page<EquipmentBorrowDTO> getPendingReturnApplications(EquipmentBorrowQueryRequest request) {
        request.setStatus("BORROWED");
        return listBorrowRecords(request);
    }

    @Override
    @Transactional
    public void batchDeleteBorrowRecords(List<Long> ids) {
        if (ids == null || ids.isEmpty()) {
            return;
        }
        
        equipmentBorrowMapper.deleteBatchIds(ids);
    }

    @Override
    public byte[] exportBorrowData(EquipmentBorrowQueryRequest request) {
        // 这里可以实现Excel导出逻辑
        // 暂时返回空数组
        return new byte[0];
    }

    /**
     * 获取当前用户ID
     */
    private Long getCurrentUserId(Authentication authentication) {
        if (authentication == null || authentication.getPrincipal() == null) {
            throw new RuntimeException("用户未登录");
        }
        
        Object principal = authentication.getPrincipal();
        if (principal instanceof com.carol.lmsbe.security.JwtAuthenticationFilter.UserPrincipal) {
            return ((com.carol.lmsbe.security.JwtAuthenticationFilter.UserPrincipal) principal).getUserId();
        } else if (principal instanceof String) {
            // 如果principal是用户名，则通过用户名查找用户ID
            User user = userMapper.selectOne(new LambdaQueryWrapper<User>()
                    .eq(User::getUsername, principal));
            if (user != null) {
                return user.getId();
            }
        }
        
        throw new RuntimeException("无法获取当前用户信息");
    }
}
